home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Information
/
CSMP Digest
/
volume 1
/
csmp-v1-173.txt
< prev
next >
Wrap
Text File
|
1992-12-31
|
49KB
|
1,439 lines
C.S.M.P. Digest Sun, 04 Oct 92 Volume 1 : Issue 173
Today's Topics:
Beginner's question on StandardPutFile
Hacking Think_C Malloc, need big free!
GetPictInfo bug with QuickTime Picts?
Is there a PD console package for Mac?
Fortran callable rountines in THINK C
Dylan and Newton PDAs
Packing Rects into the smallest possible container
Directory Scan Revisited
The Comp.Sys.Mac.Programmer Digest is moderated by Michael A. Kelly.
The digest is a collection of article threads from the internet newsgroup
comp.sys.mac.programmer. It is designed for people who read c.s.m.p. semi-
regularly and want an archive of the discussions. If you don't know what a
newsgroup is, you probably don't have access to it. Ask your systems
administrator(s) for details. (This means you can't post questions to the
digest.)
Each issue of the digest contains one or more sets of articles (called
threads), with each set corresponding to a 'discussion' of a particular
subject. The articles are not edited; all articles included in this digest
are in their original posted form (as received by our news server at
cs.uoregon.edu). Article threads are not added to the digest until the last
article added to the thread is at least one month old (this is to ensure that
the thread is dead before adding it to the digest). Article threads that
consist of only one message are generally not included in the digest.
The entire digest is available for anonymous ftp from ftp.cs.uoregon.edu
[128.223.8.8] in the directory /pub/mac/csmp-digest. Be sure to read the
file /pub/mac/csmp-digest/README before downloading any files. The most
recent issues are available from sumex-aim.stanford.edu [36.44.0.6] in the
directory /info-mac/digest/csmp. If you don't have ftp capability, the sumex
archive has a mail server; send a message with the text '$MACarch help' (no
quotes) to LISTSERV@ricevm1.rice.edu for more information.
The digest is also available via email. Just send a note saying that you
want to be on the digest mailing list to mkelly@cs.uoregon.edu, and you will
automatically receive each new issue as it is created. Sorry, back issues
are not available through the mailing list.
Send administrative mail to mkelly@cs.uoregon.edu.
-------------------------------------------------------
From: ewu1@husc8.harvard.edu (Elwin Wu)
Subject: Beginner's question on StandardPutFile
Date: 1 Sep 92 12:01:59 GMT
I'm having trouble getting the volume reference number returned by the
StandardPutFile routine. I want to use SetVol and my code typically
looks something like this (I'm using Think C 5.0):
StandardPutFile(prompt,defaultName,&theReply);
SetVol(theReply.sfFile.vRefNum);
Should I use something other that SetVol??? Any help would be
appreciated. Thanks
+++++++++++++++++++++++++++
From: keith@taligent.com (Keith Rollin)
Organization: Taligent
Date: Tue, 1 Sep 1992 18:39:23 GMT
In article <ewu1.715348919@husc8>, ewu1@husc8.harvard.edu (Elwin Wu) writes:
>
> I'm having trouble getting the volume reference number returned by the
> StandardPutFile routine. I want to use SetVol and my code typically
> looks something like this (I'm using Think C 5.0):
>
> StandardPutFile(prompt,defaultName,&theReply);
> SetVol(theReply.sfFile.vRefNum);
>
> Should I use something other that SetVol??? Any help would be
> appreciated. Thanks
IMHO, you should replace the line containing SetVol with a blank line.
"theReply.sfFile" contains everything you need to access the file. If you want
to open the data for, call FSpOpenDF. If you want to open the resource fork,
call FSpOpenResFile. You don't need to change the default directory.
If, for some arcane reason, you feel you _do_ need to change the default
directory, do it thusly:
GetVol(nil, &oldVol);
HSetVol(nil, theReply.sfFile.vRefNum, theReply.sfFile.parID);
DoMyStuff();
SetVol(nil, oldVol);
- --
Keith Rollin
Phantom Programmer
Taligent, Inc.
+++++++++++++++++++++++++++
From: d88-jwa@byse.nada.kth.se (Jon W{tte)
Organization: Royal Institute of Technology, Stockholm, Sweden
Date: Tue, 1 Sep 1992 23:10:56 GMT
@husc8.harvard.edu (Elwin Wu) writes:
I'm having trouble getting the volume reference number returned by the
StandardPutFile routine. I want to use SetVol and my code typically
looks something like this (I'm using Think C 5.0):
StandardPutFile(prompt,defaultName,&theReply);
SetVol(theReply.sfFile.vRefNum);
Should I use something other that SetVol??? Any help would be
appreciated. Thanks
Why on EARTH would you do this?
You're on System 7, since you use StandardPutFile, and there is
not a single thing under System 7 that requires a volume or wdRefNum.
Use the FSpCalls; they're there for you and the FSSpec returned
in theReply is all you need. (If you want to do a SetVol to open
a file using fopen:
1) Don't use fopen since it stinks on the mac... or
2) Do a HGetVol, HSetVol, fopen, and HSetVol back to what you
got from HGetVol)
- --
Jon W{tte, h+@nada.kth.se, Sweden, Phone +46-8-107069
White, Literate, Employed, Higher-Educated, Male, Straight and Not Poor.
I must be a bad guy.
---------------------------
From: brunner@crchh447.bnr.ca (James Brunner)
Subject: Hacking Think_C Malloc, need big free!
Organization: Bell-Northern Research, Richardson, Tx
Date: Mon, 31 Aug 1992 22:36:42 GMT
Howdy, I'm working on a kludge where I am combining several UNIX utilities.
Each of these allocates memory and it gets freed automatically at exit(0).
I would like to be able to free all malloc-allocated memory between calls
to these utils. I've looked at alloc.c but it's all in asm and hard to read.
How can the library be modified to add a free_all routine?
- --
- ---------------------------------------------------------------------------
Jim Brunner - (brunner@bnr.ca)
All opinions are my own and have nothing whatsoever to do with BNR, NT,
NTI, Bell Canada, or any of the BCE corporations or affiliates.
+++++++++++++++++++++++++++
From: reed@snake.tc.cornell.edu (Michael G. Reed)
Organization: Cornell National Supercomputing Facility
Date: Tue, 1 Sep 1992 12:06:52 GMT
In article <1992Aug31.223642.1858@bnr.ca>, brunner@crchh447.bnr.ca (James Brunner) writes:
|> Howdy, I'm working on a kludge where I am combining several UNIX utilities.
|> Each of these allocates memory and it gets freed automatically at exit(0).
|> I would like to be able to free all malloc-allocated memory between calls
|> to these utils. I've looked at alloc.c but it's all in asm and hard to read.
|>
|> How can the library be modified to add a free_all routine?
If I remember correctly, ThinkC's malloc (and calloc for that matter) are
simply mapped into calls to the memory manager call NewPtr. Therefore, the
only way to "free-all" would be to free everything in the heap (which would
be VERY bad, because you would free your code as well...). I'm not sure how
to do it (I don't have IMs here at work yet), and for that matter, I'm not
sure this would even work, but I think you could create a new heap, set your
current heap (zone?) into that heap, do all your allocation and then simply
destroy the heap for your "free-all". Sound plausible?
- -Michael
- -----------------------------------------------------------------------------
Michael G. Reed (reed@Theory.TC.Cornell.edu)
Cornell National Supercomputing Facility (607)/254-8806
- -----------------------------------------------------------------------------
Why be normal, it's boring; and boring people should be shot.
Note: These are not the views of my employer (and probably not mine either).
---------------------------
From: mpradhan@medicine.adelaide.edu.au (Malcolm Pradhan)
Subject: GetPictInfo bug with QuickTime Picts?
Date: 28 Aug 92 00:12:22 GMT
Organization: Faculty of Medicine, University of Adelaide
Hello all,
I'm using GetPictInfo to request a 256 colour palette from a 32 bit
image. Normally this works fine and I simply set the window's palette
to the one returned by GetPictInfo and copybits using ditherCopy, ie.
err= GetPictInfo((PicHandle)pictH, &pictInfoRec, returnPalette,
256, popularMethod, 0);
SetPalette(myWindow, pictInfoRec.thePalette, TRUE);
I have found that if the PICT is quicktime compressed (JPEG, Video)
no palette is returned and no error is signalled from the GetPictInfo
call - pretty frustrating.
The only way I can see of getting around this is to create an gworld,
draw the compressed PICT into it and then GetPixMapInfo. Tedious and
memory intensive!
Has anyone found a way of getting a clut or palette from a QT compressed
PICT? Is this a known bug which will soon be fixed in System 7.1 and
QT 1.5? :-)
Regards
Malcolm
_________________________________________________________________
Malcolm Pradhan
Medical Computing, Faculty of Medicine _--_|\
University of Adelaide, South Australia / \
InterNet: mpradhan@medicine.adelaide.edu.au \_.--x_/
Fax: +618 223 2076 :x marks the spot: v
+++++++++++++++++++++++++++
From: pxi@lesti.hut.fi (Pekka M Salonen)
Organization: Helsinki University of Technology, Finland
Date: 1 Sep 92 23:17:10
In article <8350@sirius.ucs.adelaide.edu.au> mpradhan@medicine.adelaide.edu.au (Malcolm Pradhan) writes:
...
< I have found that if the PICT is quicktime compressed (JPEG, Video)
< no palette is returned and no error is signalled from the GetPictInfo
< call - pretty frustrating.
< The only way I can see of getting around this is to create an gworld,
< draw the compressed PICT into it and then GetPixMapInfo. Tedious and
< memory intensive!
< Has anyone found a way of getting a clut or palette from a QT compressed
< PICT? Is this a known bug which will soon be fixed in System 7.1 and
< QT 1.5? :-)
< Regards
< Malcolm
In Mac Q&A in develop issue 11 this was discussed, here's a quote:
"Q Is it my imagination, or does GetPictInfo return a bit depth of 1 on
QuickTime compressed PICT files?
A Yep! This is what's happening: The Picture Utilities Package doesn't know of
the QuickTime Compressed Pixmap opcode (0x8200), so it just skips over the
opcode's data; then it finds the PackBitRect opcode containing the
black-and-white pseudo-alert that you get when you draw the picture on a
machine that doesn't have QuickTime installed, and GetPictInfo reports back
this alert.
Trivia: When QuickTime is installed, it displays the compressed image and
then ignores the following PackBitRect since QuickTime knows it's only
the black-and-white alert."
Reprinted here sans permission, don't think anybody will mind.
So this is a known thingie. That's all I know.
pekka
- --
ha!
---------------------------
From: vladimir@intrepid.intrepid.com (Vladimir Vukicevic)
Subject: Is there a PD console package for Mac?
Date: 30 Aug 92 19:13:35 GMT
Organization: Intrepid Technology, Inc.
Does anyone know of a PD 'console' package, like THINK provides? I have THINK C,
but I am really looking for the source of one, because I would like to add
more features (I am writing a CLI). If there isn't one, does anyone know
of a way to do I/O on the mac (with, for example, printf() & fgets()...)?
I was thinkning of creating a window, and then using TextEdit, but I can't
figure out a way to make the prompt non-overwriteable, and how to get a specific
part of the text. Any ideas? Suggestions? Comments?
- Vladimir
- vladimir@intrepid.com
- --
- -------------------------------------------------------------------------------
Internet................vladimir@intrepid.com
^[:r std.disclaimer
+++++++++++++++++++++++++++
From: siegel@world.std.com (Rich Siegel)
Organization: GCC Technologies
Date: Tue, 1 Sep 1992 12:39:59 GMT
In article <1992Aug30.191335.4377@intrepid.com> vladimir@intrepid.intrepid.com (Vladimir Vukicevic) writes:
>Does anyone know of a PD 'console' package, like THINK provides? I have THINK C,
>but I am really looking for the source of one, because I would like to add
>more features (I am writing a CLI). If there isn't one, does anyone know
>of a way to do I/O on the mac (with, for example, printf() & fgets()...)?
>I was thinkning of creating a window, and then using TextEdit, but I can't
>figure out a way to make the prompt non-overwriteable, and how to get a specific
>part of the text. Any ideas? Suggestions? Comments?
The source for the ANSI library is included with THINK C; there's no
particular reason you can't use that as a basis.
R.
- --
- -----------------------------------------------------------------------
Rich Siegel Internet: siegel@world.std.com
Software Engineer & Toolsmith
GCC Technologies
+++++++++++++++++++++++++++
From: bpb9204@tamsun.tamu.edu (Brent)
Date: 1 Sep 92 18:14:39 GMT
Organization: Texas A&M Univ., Inc.
vladimir@intrepid.intrepid.com (Vladimir Vukicevic) writes:
|Does anyone know of a PD 'console' package, like THINK provides? I have THINK C,
|but I am really looking for the source of one, because I would like to add
|more features (I am writing a CLI). If there isn't one, does anyone know
|of a way to do I/O on the mac (with, for example, printf() & fgets()...)?
|I was thinkning of creating a window, and then using TextEdit, but I can't
|figure out a way to make the prompt non-overwriteable, and how to get a specific
|part of the text. Any ideas? Suggestions? Comments?
Vladimir,
Good news! I've done this exact thing and I posted info about it many months
ago but got no response (nobody needed it then, I guess). What I have done
is to create a "shell" window that has a simple TextEdit area. The
area has a typical prompt printed that the user cannot change. The user
is allowed to type, edit, copy, paste, etc into this area and then when
the user hits the <Enter> key, the program sucks the new text out that the
user entered. Processing is not done for the <Return> key; therefore, the
entered text may have line breaks in it.
The prompt text string is stored in a resource and can be changed.
There is also a basic routine to Print() strings to the window (what you
put in the string to print is up to you -- use NumToStr(), sprintf(),
whatever).
I'll gladly make the source available to anybody interested.
- -Brent
+++++++++++++++++++++++++++
From: haney@moonshine.llnl.gov (Scott W. Haney)
Date: 1 Sep 92 22:14:18 GMT
Organization: Magnetic Fusion Energy - LLNL
[Stuff asking about a PD shell window]
>Vladimir,
>Good news! I've done this exact thing and I posted info about it many months
>ago but got no response (nobody needed it then, I guess). What I have done
>is to create a "shell" window that has a simple TextEdit area. The
>area has a typical prompt printed that the user cannot change. The user
>is allowed to type, edit, copy, paste, etc into this area and then when
>the user hits the <Enter> key, the program sucks the new text out that the
>user entered. Processing is not done for the <Return> key; therefore, the
>entered text may have line breaks in it.
[...]
>I'll gladly make the source available to anybody interested.
>-Brent
Brent,
Please tell us how to get a copy of your shell package. I could make
use of this sort of thing today. One question: does it support sessions
longer that 32K (a common limitation for things based on TextEdit)?
Scott
- --
- -------------------------------------------------------------------------
Scott W. Haney || Lawrence Livermore N'Lab || The above views are
haney@random.llnl.gov || P.O. Box 808; L-644 || mine and not neces-
(510) 423-6308 || Livermore, CA 94550 || sarily LLNL's.
+++++++++++++++++++++++++++
From: bpb9204@tamsun.tamu.edu (Brent)
Organization: Texas A&M Univ., Inc.
Date: Tue, 1 Sep 1992 23:24:24 GMT
haney@moonshine.llnl.gov (Scott W. Haney) writes:
|
| [..shell info deleted...]
|
|Brent,
| Please tell us how to get a copy of your shell package. I could make
|use of this sort of thing today. One question: does it support sessions
|longer that 32K (a common limitation for things based on TextEdit)?
OK. Let me just make a few comments about what exactly I have.
I think "package" is the wrong word; I tend to think of a package as a
library. What I *do* have is a small application that shows how to do
this type of processing. The runnable application is only some 8K in size,
and the code is moderately readable.
What it does now is: lets the user type their info in (whatever it may be).
When the enter key is pressed, the program reads all the text entered after
the prompt. Everything *before* the prompt is deleted.
What this does is allows the last "command" to remain displayed. This is
very hard to describe here; you'll have to check out the program.
In other words, the text actually stored in the textedit record is rarely
more than 1K; so yes, the program handles the 32k barrier fine. This
"feature" of deleting old data is easily modifiable to store say, the last
16000 characters.
As far as getting it goes, if you would like a copy, please reply via
email. I will eventually post it to comp.binaries.mac, but it'd be quickest
to email it to anyone who is interested and wants/needs it now. The
source and executable is only 44k (binhexed).
I'll compile a list of people and zap it out in a few days, OK?
- -Brent
---------------------------
From: cconstantine@galaxy.gov.bc.ca
Subject: Fortran callable rountines in THINK C
Date: 1 Sep 92 11:30:40 -0700
Organization: BC Systems Corporation
I will be working on a program with a friend of mine that will interface some
Fortran code (Language Systems) and would like my C libraries to be callable
form Fortran. Is there a specific way I need to do this? I'm using THINK C
5.0.2 on an LCII (now called a Perforama 400) and System 7.0.1 w/ tune-up.
Thanks muchly!!!!
- --
Carl B. Constantine
CCONSTANTINE@galaxy.gov.bc.ca
"Opinions are mine only!!"
+++++++++++++++++++++++++++
From: jhl@naif.jpl.nasa.gov (Jay Lieske)
Organization: Jet Propulsion Laboratory
Date: Tue, 1 Sep 1992 21:14:01 GMT
In article <1992Sep1.113040.943@galaxy.gov.bc.ca> cconstantine@galaxy.gov.bc.ca
writes:
>I will be working on a program with a friend of mine that will interface some
>Fortran code (Language Systems) and would like my C libraries to be callable
>form Fortran. Is there a specific way I need to do this? I'm using THINK C
>5.0.2 on an LCII (now called a Perforama 400) and System 7.0.1 w/ tune-up.
>
>Thanks muchly!!!!
>--
>Carl B. Constantine
>CCONSTANTINE@galaxy.gov.bc.ca
> "Opinions are mine only!!"
>
In principle, I think it can be done, but it's rather tough with Think
products. Specifically, I tried this a few years ago using Think Pascal.
The basic problem is that Think compilers are case-sensitive and its
linker is case-insensitive whereas the MPW Pascal compiler is case
insensitive but the linker is case-sensitive. For Pascal programs that
means that the ENTRY points must be all caps. One interesting and
potentially useful side effect of all this is that Think and MPW libraries
may be intermixed--for example MPW's NEWPTR is "different" from
Think's NewPtr because of the capitalization.
At one time Rich Siegel mentioned that Think Pascal might look into
the problem, but I don't believe they have done anything up to now. It's
much easier just to recompile things with MPW compilers (after using
Think's excellent debugging tools) and link with Language Systems Fortran.
Jay H. Lieske jhl@naif.jpl.nasa.gov
+++++++++++++++++++++++++++
From: TOGE@SLACVM.SLAC.STANFORD.EDU (Nobukazu Toge)
Date: 2 Sep 92 01:58:57 GMT
Organization: Stanford Linear Accelerator Center
Carl -
LS Fortran knows to interface with MPW C, Pascal and so on. See Appendix F
(p.375) of LSF 3.0 manual. So if you convert your ThC libraries into MPW
you will be all set. I understand that MPW .o -> ThC lib conversion is
possible, but I'm not sure about the other way around [which is what you
need]. Check out the ThC manual.
If it turns out not so straightforward you may consider porting
your Th C source files and recompile them with MPW C. The mac .h files
on Th C v.5.0.x are very similar to (or identical to) MPW interfaces.
Except,if you are accessing low memory globals by using LoMem.h in the
{Think #includes} folder, you should modify them to use SysEqu.h. Otherwise
strange errors will happen on MPW. Another thing is A4/A5 world stuff, but
that probably is a non-issue unless you are writing code resources, not
ordinary library routines.
- - Nobu Toge (ex-SLAC, now-KEK. My opinions only).
---------------------------
From: chrisv@runx.oz.au (Chris Velevitch)
Subject: Dylan and Newton PDAs
Organization: RUNX Un*x Timeshare. Sydney, Australia.
Date: Tue, 1 Sep 92 15:35:35 GMT
I have heard that there is a new programming language called
Dylan, which is being used to build compact cross-platform
applications for the Mac, Newton PDAs and Unix workstations.
Is is available yet? If it is available, how does one test an
application if you don's have access to a PDA? I also have
heard that there is a new fully pre-emptive multitasking
operation systems for the Newton called NewtOS. Will NewtOS
be available for the Mac or a NewtOS emulator to allow
testing of OS related functions?
- --
Chris Velevitch
Internet: chrisv@runxtsa.runx.oz.au
UUCP: ...!uunet!munnari!runxtsa.runx.oz.au!chrisv
Voice: +61 2 906 6100, Fax: +61 2 906 6069
+++++++++++++++++++++++++++
From: joseph@joebloe.maple-shade.nj.us (Joseph Nathan Hall)
Date: 2 Sep 92 04:01:08 GMT
Organization: 5 Sigma Software
In article <1992Sep1.153535.2391@runx.oz.au> (comp.sys.mac.programmer), chrisv@runx.oz.au (Chris Velevitch) writes:
) I have heard that there is a new programming language called
) Dylan, which is being used to build compact cross-platform
) applications for the Mac, Newton PDAs and Unix workstations.
) Is is available yet? [etc....]
This has been a topic off and on in MacWeek for a while now. Apparently
Apple is leaning toward supporting only large developers for the Newton.
Apple would like to shape the initial product and perception quite
carefully. Whether that might prevent it from being useful, who knows.
There has also been some discussion about whether Dylan will be just
too damned slow as an implementation language.
In any event, the shipping date has already started to slide a la
System 7, so I wouldn't worry too much about writing yer own Newton
apps yet.
uunet!joebloe!joseph (609) 273-8200 day joseph%joebloe@uunet.uu.net
v v sssss | Certified Guru: all-grain brewing,| 2102 Ryan's Run East
v v s s | C, synthesizer comp & arranging, | Rt 38 & 41
v sss | photography. Also not a bad cook. | Maple Shade NJ 08052
- -----My employer isn't paying for this, and my opinions are my own-----
---------------------------
From: tj@kona.cs.ucla.edu (Tom Johnson)
Subject: Packing Rects into the smallest possible container
Date: 12 Aug 92 01:35:21 GMT
Organization: UCLA Computer Science Department
Hi-
I'm sure that what I'm about to ask has been covered in many books and
in many articles, since it sounds like one of those typical cs/math puzzles.
But I don't have any books that help, and I'm looking for some ideas.
I'm not looking for the "perfect" algorithm, just something efficient
and reasonable. So here goes my question:
I have a bunch of rectangular objects, and I would like to pack them into
the smallest possible rectangular container (we're only dealing with 2
dimensions here, I'm not concerned with 3d boxes). How do I do this?
The objects may all have different sizes.
Any suggestions for algorithms? Ideas?
This shouldn't be too difficult, but I can't seem to come up with something
I like.
Tom
btw, I would imagine that this would become really interesting with
other shapes, but all I really care about is rectangles.
- --
Tom Johnson "They say Confucious does his crossword with a pen."
tj@cs.ucla.edu -Tori Amos
+++++++++++++++++++++++++++
From: zben@ni.umd.edu (Charles B. Cranston)
Organization: UM Home for the Terminally Analytical
Date: Wed, 12 Aug 1992 20:26:24 GMT
In article <1992Aug12.013521.28314@cs.ucla.edu>,
tj@kona.cs.ucla.edu (Tom Johnson) wrote:
> I have a bunch of rectangular objects, and I would like to pack them into
> the smallest possible rectangular container (we're only dealing with 2
> dimensions here, I'm not concerned with 3d boxes). How do I do this?
> The objects may all have different sizes.
> Any suggestions for algorithms? Ideas?
This sounds a lot like a two-dimensional version of what has come to be
called "the knapsack problem" in computer science literature. You might
be able to find some work being done if you use this buzzword.
Actually, the knapsack problem is usually explained in terms of fitting
the maximum amount of stuff in a knapsack of known size, i.e., given a
set of integers {I} and a number N find the maximal subset {i} such
that sum({i}) <= N or something like that. In your case it is more
like finding the minimal N which for the one-dimensional case is simply
sum({I}).
The knapsack problem is thought to be NP-complete. In fact, it was one
of the other schemes besides the factoring problem (RSA) considered for
use in public-key encryption algorithms...
zben@ni.umd.edu -KA3ZDF
+++++++++++++++++++++++++++
From: root@lyra.scg.hac.com (Dave Fisher)
Date: 1 Sep 92 23:10:02 GMT
Organization: Hughes Aircraft Co., Carlsbad, CA
The "knapsack" problem is close; but a perfect fit of your problem
is the VLSI problem called "2-D placement" or "bin packing".
Many algorithms have been published. There are approaches that
use optimization techniques, such as "greedy algorithms", "genetic
algorithms", "spin-glass" (this one looked excellent but difficult),
"simulated annealing", etc. There have also been heuristic rule-based
systems, straight algorithms, etc.
The best source for info is probably the conference proceedings for
the "Design Automation Conference" (DAC), published annually. Also try
the journal called "VLSI". Or ask a local VLSI CAD expert for some
good references.
If you end up writing your own algorithm, here are a couple of tips:
1. Place larger blocks first
2. Try to find groups of 2 or more blocks which have a common width
or length and line them up -- this is very efficient.
3. Allow for switching things around randomly, to try different possibilities.
4. Watch out for getting stuck in "local minima" if using #3.
Good luck!
Dave
---------------------------
From: aep@world.std.com (Andrew E Page)
Subject: Directory Scan Revisited
Date: 1 Sep 92 14:00:08 GMT
Organization: The World Public Access UNIX, Brookline, MA
I'm just about finished with the code for the directory scan code. I've
incorporated some recomenedations from Apple, and I am in the process of
commenting the code heavily.
However, here is the interface file. Comments and suggestestions are
welcome.
- --------CUT HERE------------------------------------------------CUT HERE------
#ifndef __DIRSCAN__
#define __DIRSCAN__
#ifndef __TYPES__
#include <Types.h>
#endif
Ptr StartDirScanDirID(short volRef, long dirID, int numTypes, OSType *TypeList, pascal Boolean (*filter)(FileParam *f)) ;
/*
* StartDirScanDirID starts the directory scan, using a WDVRefNum.
* It will return 0L if the call failed or a pointer to be used
* in subsequent calls.
*
*
* volRef true volume reference where scan is to start.
*
* dirID directory on volume where scan is to start.
*
* numTypes Number of types to limit scan too.
* -1 indicates to scan all types.
*
* typeList Array of OSTypes with numTypes elements.
* Pass 0L if numTypes is -1
*
* filter Filter proc of the variety used by SFGetFile.
* Pass 0L for no filtering.
*
* pascal Boolean MyFilter(fileParamPtr *f) ;
* MyFilter returns TRUE if file is to be excluded.
* or FALSE if it isn't.
*/
Ptr StartDirScanWDVRef(short vRef, short *volRef, int numTypes, OSType *TypeList, pascal Boolean (*filter)(FileParam *f)) ;
/*
* StartDirScanWDVRef starts the directory scan, using a WDVRefNum.
* It will return 0L if the call failed or a pointer to be used
* in subsequent calls.
*
*
* vRef Volume/Directory where scan is to start.
*
* volRef pointer a short where the true volume reference
* number is to be placed when call is complete.
*
* numTypes Number of types to limit scan too.
* -1 indicates to scan all types.
*
* typeList Array of OSTypes with numTypes elements.
* Pass 0L if numTypes is -1
*
* filter Filter proc of the variety used by SFGetFile.
* Pass 0L for no filtering.
*
* pascal Boolean MyFilter(fileParamPtr *f) ;
* MyFilter returns TRUE if file is to be excluded.
* or FALSE if it isn't.
*/
OSErr GetNextDirScanFile(Ptr scanPtr, char *fName, long *dirID, long *level) ;
/*
* Each call to GetNextScanFile will retreive the next file in the
* directory tree. GetNextScanFile will return a fnfErr when the
* scan is completed.
*
*
* scanPtr Ptr returned from StartScan
*
* fName string space for returned file name (recommended length 64)
*
* dirID Pointer to a long where dirID reference for
* the directory that the file is in.
*
* level Pointer to a long where the level at which the file was found
* (0 is the level where the scan started). You can pass a 0L
* in place of pointer if the level is not of interest.
*
*/
OSErr StopDirScan(Ptr scanPtr) ;
/*
* Terminates the scan started by Start scan.
*
* scanPtr Ptr returned by StartScan.
*
* CAUTION... do not not attempt to use scanPtr again
* after this call.
*
*/
/*
* Using information returned from GetNextScanFile this function
* will return a 'full pathname' as a handle. The handle is the
* exact length of the string and is NOT preceded by a pascal length
* byte or folled by a C null terminator.
*
* fName Name of the file.
*
* vRef True volume reference number.
*
* dirID directory ID that the file resides in.
*/
Handle FullPathNameID(char *fName, int vRef, long dirID) ;
#endif
- --
Andrew E. Page CTO(Warrior Poet)| Decision and Effort The Archer and Arrow
DSP Ironworks | The difference between what we are
Macintosh and DSP Technology | and what we want to be.
+++++++++++++++++++++++++++
From: aep@world.std.com (Andrew E Page)
Date: 2 Sep 92 19:04:54 GMT
Organization: The World Public Access UNIX, Brookline, MA
Here is the directory scanning code. Written under MPW 3.2.
- --------CUT HERE------------------------------------------------CUT HERE------
#ifdef USE_PRECOMPILE
#pragma load ":Headers:dirscanh.hpc"
#endif
#ifndef __ERRORS__
#include <Errors.h>
#endif
#ifndef __FILES__
#include <Files.h>
#endif
#ifndef __MEMORY__
#include <Memory.h>
#endif
#ifndef __TOOLUTILS__
#include <ToolUtils.h>
#endif
#ifndef __DIRSCAN__
#include <dirscanh.h>
#endif
#ifdef PRECOMPILE
#undef PRECOMPILE
#pragma dump ":Headers:dirscanh.hpc"
#endif
/*
dirscan.c by Andrew E. Page. Macintosh Directory Scanning Code
The code operates as follows.
At the start of the scan StartScan accepts the directory in
which to start. It initializes all the structures, starting
the scan in the directory at index 1, which is the first file
in the given directory. For each call to GetNextScanFile the
file information for the current index is fetched, and the index
is incremented by one. The entry is checked to see if it is
a directory. If so the current state of the scan, the current
directory being scanned and the index for the next file, is pushed
onto a 'stack', and a recursive call to GetNextScanFile is made.
If PBGetCatInfo returns a "File Not Found" error (-43 fnfErr)
occurs during the scan the state of the stack is checked. If
the stack is 'empty' (n_stackEntries == 0) then the scan is
at the top of the directory tree and has accessed the last
file, and the tree is exhasted. Any other error should cause
the termination of the scan (this depends on how the code is
being used at a higher level however).
If the stack is not empty then the last entry is 'popped' off
of the stack and scanning resumes at that level.
Example:
Consider the following directory tree. With the vRefNum for <startdir>
passed to StartScan, the files would be returned in the following
order.
file1a file1b file3a file3b file2a file2b file1c file4a
<startdir>
|
|
|
file1a file1b <dir1a> file1c <dir1b>
| |
| |
| |
<dir2a> file2a file2b |
| |
| |
| |
file3a file3b |
|
|
file4a
*/
typedef struct {
long dirID ; // the reference for the directory
short index ; // what index it stopped scanning at
} StackEntry_t ;
typedef struct {
/*
* these fields provide
* control over the 'stack'. Which
* saves the state of the scan from one
* level to the next.
*/
StackEntry_t **entries ; // container for the entries
long n_stackEntries ; // number of entries currently in stack
long maxStackEntries ; // maximum entries stack can hold
long level ; // directory level we've decended to
/*
* Storage space for the Parameter Block record. This allows
* us to recycle certain fields without having to constantely
* reinitialize them.
*/
CInfoPBRec F ; // CInfo Rec ref IM IV-125
/*
* filtering parameters
*/
short doFiltering ; // is filtering necessary?
int numTypes ; // number of OSTypes to check for
OSType *TypeList ; // List of the types to check
pascal Boolean (*filter)(FileParam *f) ; // filter function to be called for each file
} ScanControl_t ;
/*
* We start off with a stack with a capacity for 32 entries. Allowing
* us to descend 32 levels without having to reallocate any more memory.
* That should be sufficient for most applications. However, more
* memory will be allocated if need be. Each allocation will only
* require 192 additional bytes.
*
* Season to taste here, just so long as STACK_BLOCK_INCREMENT >= 1
*/
#define STACK_BLOCK_INCREMENT 32
/*
* This is an internal function, hence the static qualifier.
* This provides the "push" or store function of a standard LIFO(Last In First Out)
* queue. Otherwise called a 'stack'.
*
* Each time that it is called it stores the entry, in our case the directory
* ID where the scan is 'branching' from, and the index in that directory where the
* branch is taken, stores them in the container, and then increments the stack
* pointer by one to make room for the next entry. This differs slightly from the
* nature of the 68XXX stack in as much as for a 68XXX stack the pointer is
* predecremented to make space for the new entry.
*
* Entries are retrieved from this stack with the PopFromStack function.
*/
static PushToStack(ScanControl_t *SC, long dirID, short index)
{
if( SC->n_stackEntries == SC->maxStackEntries )
{
/*
* Make room for more entries
*/
SC->maxStackEntries += STACK_BLOCK_INCREMENT ;
SetHandleSize((Handle)SC->entries, sizeof(StackEntry_t) * SC->maxStackEntries) ;
}
/*
* put the entry on the stack
*/
(*(SC->entries))[SC->n_stackEntries].dirID = dirID ;
(*(SC->entries))[SC->n_stackEntries].index = index ;
SC->n_stackEntries += 1 ;
SC->level += 1 ;
} /* end of PushToStack */
/*
* This is an internal function, hence the static qualifier.
* This provides the "pop" or retrieve function of a standard LIFO(Last In First Out)
* queue. Otherwise called a 'stack'.
*
* Each time that it is called it restores the state of the scan from where
* it had 'branched' in descending to another directory level. It starts by
* decrementing the 'stack pointer' so that it points at the last entry that was
* placed on the stack by the PushToStack function.
*/
static PopFromStack(ScanControl_t *SC, long *dirID, short *index)
{
SC->n_stackEntries -= 1 ;
SC->level -= 1 ;
*index = (*(SC->entries))[SC->n_stackEntries].index ;
*dirID = (*(SC->entries))[SC->n_stackEntries].dirID ;
} /* end of PopFromStack */
#ifndef FALSE
#define FALSE 0
#define TRUE 1
#endif
/*
* This internal function determines whether or not this is a type
* of file that we are looking for. It first checks the files 'type'
* against the list of types provided by the user, or simply passes it
* on if the numTypes was specified as -1.
* If it succeeds in passing that check it then executes the 'filter' function
* if supplied by the caller.
*/
static Boolean doFilter(ScanControl_t *SC, FileParam *f)
{
int i ;
short isType = FALSE ;
/*
* check against types
*/
if( SC->numTypes != -1 )
{
for( i = 0 ; i < SC->numTypes ; i++ )
{
if( SC->TypeList[i] == f->ioFlFndrInfo.fdType )
{
isType = TRUE ;
break ;
}
}
/*
* Is this one of the file types that we are looking for?
* if not then exclude it from the list.
*/
if( !isType )
return TRUE ;
}
/*
* Perform any additional filtering with the
* filter proc specified by the caller.
*/
if( SC->filter )
return (*SC->filter)(f) ;
/*
* Otherwise if we've reached this point
* we do not want this filtered from the list
*/
return FALSE ;
}
/*
* This is essentially the core starting routine. It will also be used
* when starting a scan with a WDVRef instead of a ioDirID.
*
* Initializes all the fields necessary, setting up the Parameter
* block for subsequent calls to GetNextDirScanFile.
*
* Sets up the Stack's controlling data structures, initializing the stack
* pointer to 0 and allocating an initial block of entries.
*
* Does some pre-filter checks to optimize for the case where no filtering
* is required. It copies the TypeList to ensure that the data remains
* valid if this function is being called from a routine where the TypeList
* may reside in the stack frame that may be deallocated before calls to
* GetNextScanFile.
*
*/
Ptr StartDirScanDirID(short volRef, long dirID, int numTypes, OSType *TypeList, pascal Boolean (*filter)(FileParam *f))
{
ScanControl_t *SC ;
StackEntry_t **entries ;
OSType *theTypes ;
long len ;
/*
* Setup the control structure(s)
* At each allocation check to ensure that we
* got the space asked for. If not, deallocate any
* previous allocated memory and return a 0L, indictating
* that the setup failed.
*/
/*
* Check to see if the caller has provided a type list.
* This will be the case if numTypes is > 0.
* If so copy the list to ensure that it remains valid.
*/
if( numTypes > 0 )
{
/*
* Make space for the copy of the TypeList.
*/
theTypes = (OSType *)NewPtr(len = numTypes * sizeof(OSType)) ; // ref IM I-75
if( theTypes == 0L )
return 0L ;
/*
* copy the scan types
*/
BlockMove(TypeList, theTypes, len) ; // ref IM II-44
}
else
theTypes = 0L ;
/*
* Allocate space for the stack. Start off with STACK_BLOCK_INCREMENT
* entries. More can be added later if necessary.
*/
entries = (StackEntry_t **)NewHandle(sizeof(StackEntry_t) * STACK_BLOCK_INCREMENT) ; // ref IM I-76
if( entries == 0L )
{
DisposPtr((Ptr)theTypes) ; // ref IM I-75
return 0L ;
}
/*
* Allocate space for the overal control structure that
* will be passed back to the caller.
*/
SC = (ScanControl_t *)NewPtr(sizeof(ScanControl_t)) ; // ref IM I-75
if( SC == 0L )
{
DisposPtr((Ptr)theTypes) ; // ref IM I-75
DisposHandle((Handle)entries) ;
return 0L ;
}
/*
* Setup the filtering
*/
if( (numTypes > 0) || (filter != 0L) )
{
SC->doFiltering = TRUE ;
SC->numTypes = numTypes ;
SC->TypeList = theTypes ;
SC->filter = filter ;
}
else
{
SC->TypeList = 0L ;
SC->doFiltering = FALSE ;
}
/*
* initialize the current
* state of the scan
*/
SC->entries = entries ;
SC->n_stackEntries = 0 ;
SC->maxStackEntries = STACK_BLOCK_INCREMENT ;
SC->level = 0 ;
/*
* Setup the initial PB Rec ref IM IV-125
*/
SC->F.hFileInfo.ioCompletion = 0L ; // always initialize this field!
SC->F.hFileInfo.ioFlParID = dirID ; // Parent dirtory to start scan in.
SC->F.hFileInfo.ioVRefNum = volRef ;// true volume reference number
SC->F.hFileInfo.ioFDirIndex = 0 ; // initial scanning index. (will be incremented for each call)
return (Ptr)SC ;
} /* end of StartDirScanDirID */
/*
* This call allows us to start off with a WDVRef that may have been
* returned from SFGetFile. It returns in volRef the true volume
* reference for the volume where the working directory passed in
* vRef resides.
*/
Ptr StartDirScanWDVRef(short vRef, short *volRef, int numTypes, OSType *TypeList, pascal Boolean (*filter)(FileParam *f))
{
OSErr err ;
WDPBRec wd ;
/*
* Setup the the wd parameter block
*/
wd.ioCompletion = 0L ;
wd.ioNamePtr = 0L ;
wd.ioVRefNum = vRef ;
wd.ioWDIndex = 0 ;
/*
* obtain the WD info
*/
err = PBGetWDInfo(&wd, FALSE) ;
if( err )
return 0L ;
*volRef = wd.ioWDVRefNum ; /* the true volume reference number */
/*
* use StartDirScanDirID to initialize the scan.
*/
return StartDirScanDirID(wd.ioWDVRefNum, wd.ioWDDirID, numTypes, TypeList, filter) ;
} /* end of StartDirScan */
/*
* This function is essentially the core of the system. Each call to this function
* will produce a file, or an fnfErr when the scan is completed. Any other error is
* an indication of something else being terribly wrong.
*
* At each call the function will do the following:
*
* 1. Increment the index of the file that is currently pointing at.
*
* 2. Get the file's catalog information with PBGetCatInfo.
*
* 3. If the file is a directory it will save the state of the scan on the
* internal stack, and make a recursive call to itself to the next level.
*
* 4. If PBGetCatInfo returns with a File Not Find Error (fnfErr -43), it pops
* the last entry off of the stack, restoring the state of the scan and makes
* a recursive call to itself to return to the previous level. If the stack
* at this point is empty it returns the fnfErr to the caller indicating that
* the scan has completed.
*
* 5. If the file entry is not a directory it checks it against the types and
* filter function specified by the caller. If it is rejected by the filter,
* (when it returns TRUE) GetNextDirScanFile repeats steps 1 through 4.
*/
OSErr GetNextDirScanFile(Ptr scanPtr, char *fName, long *dirID, long *level)
{
ScanControl_t *SC = (ScanControl_t *)scanPtr ;
OSErr err ;
short flag = FALSE ;
long parID = SC->F.hFileInfo.ioFlParID ;
SC->F.hFileInfo.ioNamePtr = fName ;
do {
SC->F.hFileInfo.ioFDirIndex++ ;
SC->F.hFileInfo.ioDirID = parID ;
err = PBGetCatInfo(&SC->F, FALSE) ;
if( err )
{
/*
* Anything other than a fnfErr, or a noErr is an inidcation
* of some catastrophic failure and that the scan cannot procede.
*/
if( err != fnfErr )
return err ;
/*
* if there is an fnfErr and there are no more stack entries, this means
* that the tree that is being searched has been exhausted. Returning
* the fnfErr at this point should terminate the scan by the caller.
*/
if( SC->n_stackEntries == 0 )
return err ;
/*
* if it is a fnfErr, and entries remain in the stack, we have exhausted
* the file entries at this level and need to return to the previous level
* and resuming scanning where we left off. To do this we Pop the previous
* state of the scan off of the stack, and make a recursive call to GetNextDirScanFile.
*/
PopFromStack(SC, &SC->F.hFileInfo.ioFlParID, &SC->F.hFileInfo.ioFDirIndex) ;
return GetNextDirScanFile((Ptr)SC, fName, dirID, level) ;
}
if( SC->F.hFileInfo.ioFlAttrib & 0x10 ) // check for directory flag
{
/*
* Save the state of the scan
* at the current level.
*/
PushToStack(SC, SC->F.dirInfo.ioDrParID, SC->F.hFileInfo.ioFDirIndex) ;
/*
* Setup the the state of the next level to be
* the directory that we just found. Starting at the
* first file index.
*/
SC->F.hFileInfo.ioFlParID = SC->F.dirInfo.ioDrDirID ;
SC->F.hFileInfo.ioFDirIndex = 0 ;
return GetNextDirScanFile((Ptr)SC, fName, dirID, level) ;
}
/*
* if necessary check to see if we should filter
* out this file entry.
*/
if( SC->doFiltering )
flag = doFilter(SC, (FileParam *)&SC->F) ;
} while( flag ) ; // if file is to be filtered, try another one.
/*
* Set the directory ID parameter
*/
*dirID = SC->F.hFileInfo.ioFlParID ;
/*
* if the caller wants the level of this file set it.
*/
if( level )
*level = SC->level ;
return err ;
} /* end of GetNextDirScanFile */
/*
* This terminates the scan. What is actually does is release
* all the memory that was allocated. Since no new working
* directories were created there is no need to call PBCloseWD.
*/
OSErr StopDirScan(Ptr scanPtr)
{
ScanControl_t *SC = (ScanControl_t *)scanPtr ;
if( SC->TypeList )
DisposPtr((Ptr)SC->TypeList) ;
DisposHandle((Handle)SC->entries) ;
DisposPtr(scanPtr) ;
/*
* Although it is unlikely that we will have comitted
* any errors provide this check to the caller.
*/
return MemError() ;
}
/*
*
* This function will generate a full pathname to
* the file identified by its name, volume, and directory ID.
* The result is a handle that contains the full pathname of the
* file and is sized to fit that pathname exactly. It contains
* No length byte or null terminator. The length of the string can
* be determined with GetHandleSize.
*
*
* The function operates as a loop. At each interation through the
* the loop it gets the catalog name for the entry. Each time
* making the parent directory for that entry the target for the
* next cycle. This proceeds until it hits the root directory
* is reached, which has no logical parent, and thus PBGetCatInfo
* returned a file not found error(-43 fnfErr).
*
* We use a handle since this allows us to use the
* Munger string manipulator.
*
*/
Handle FullPathNameID(char *fName, int vRef, long dirID)
{
Handle theString = NewHandle(0) ; /* container for the string */
CInfoPBRec F ;
short err ;
char colon = ':' ; /* just in case you want to put it into a stand alone code resource */
char string[64] ;
/*
* For safety sake(to ensure that our string contains enough space for
* subsequent entries found, and to make sure that we don't overwrite
* the input string, we copy the input fileName to our own storage.
*/
BlockMove(fName, string, fName[0]+1) ; // ref IM II-44
/*
* Initialize the PB fields
*/
F.hFileInfo.ioNamePtr = string ; /* pascal string for the name, and also subsequent storage on calls */
F.hFileInfo.ioVRefNum = vRef ; /* volume reference (Gotten from SFGetFile perhaps */
F.hFileInfo.ioCompletion = 0L ; /* initialize this field or get a Serious BOMB */
F.hFileInfo.ioFDirIndex = 0 ; /* for the first call only. Get CatInfo based on ioNamePtr, ioVRefNum, and dirID */
F.hFileInfo.ioDirID = dirID ; /* directory containing this file */
while( !(err = PBGetCatInfo(&F,0)) )
{
/*
* Insert the directory level into the front of the string
*/
Munger(theString, 0, 0L, 0, &string[1], string[0]) ; // ref IM I-468
/*
* Insert a colon in front of the Directory Entry
*/
Munger(theString, 0, 0L, 0, &colon, 1) ; // ref IM I-468
/*
* We now wish to get the information about
* the directory that contains this file/directory.
* in short we are moving one level UP in the heirarchy
*/
F.dirInfo.ioDrDirID = F.dirInfo.ioDrParID ; /* get the ioDrDirID of the PARENT directory (the next level up) */
/*
* Setting this field to < 0 will
* cause PBGetCatInfo to get the catalog
* information based on the VRef and dirID
* that we've placed in F.dirInfo.ioDrDirID,
* and return the name of the entry in the
* pointer to the string in ioNamePtr.
*/
F.hFileInfo.ioFDirIndex = -1 ;
}
/*
* The last entry will be the Volume name which should not have a colon in front of it
*/
Munger(theString, 0, 0L, 1, string, 0) ;
return theString ;
}
- --
Andrew E. Page CTO(Warrior Poet)| Decision and Effort The Archer and Arrow
DSP Ironworks | The difference between what we are
Macintosh and DSP Technology | and what we want to be.
---------------------------
End of C.S.M.P. Digest
**********************